#pragma once

#include <iostream>
#include <functional>
#include <pthread.h>
#include "Sock.hpp"
#include "Protocol.hpp"

using namespace ns_protocol;

namespace ns_server
{
    class TcpServer; // 提前声明
    using func_t = std::function<Responce(const Resquest &)>; // 业务处理函数

    class ThreadDate
    {
    public:
        ThreadDate(int sock, std::string ip, uint16_t port, TcpServer *tsvp)
            : _sock(sock), _ip(ip), _port(port), _tsvp(tsvp)
        {
        }

    public:
        int _sock;
        std::string _ip;
        uint16_t _port;
        TcpServer *_tsvp;
    };

    class TcpServer
    {
    public:
        TcpServer(uint16_t &port, func_t func) : _port(port), _func(func)
        {
        }

        // 初始化服务器
        void InitServer()
        {
            _listenSock.Socket();
            _listenSock.Bind(_port);
            _listenSock.Listen();
            logMessage(Info, "init server done,listenSock:%d", _listenSock.Fd());
        }

        // 业务处理
        void ServerIO(int sock, std::string clientIp, uint16_t clientPort)
        {
            // 0.读取数据
            std::string buffer;
            while (true)
            {
                std::string package;
                int n=ReadPackage(sock,buffer,&package);
                if(n<0) return ;//读取错误
                else if(n==0) continue;//读取数据不完整

                // 1.去除报头
                std::cout<<"得到的请求:"<<package<<std::endl;
                package=RemoveHeader(package,n);
                std::cout<<"去报头后的请求:"<<package<<std::endl;

                // 2.Resquest反序列化
                Resquest res;
                res.Deserialize(package);
                //std::cout << "test:" << res._x << " " << res._op << " " << res._y << std::endl;

                // 3.业务处理
                Responce resp = _func(res);
                //std::cout<<resp._result<<" "<<resp._code<<std::endl;
                

                // 4.Responce序列化
                std::string out;
                resp.Serialize(&out);
                std::cout<<"Responce序列化:"<<out<<std::endl;

                // 5.添加报头
                out=AddHeader(out);
                std::cout<<"Responce添加报头:"<<out<<std::endl;


                // 6.发送数据
                send(_sock,out.c_str(),out.size(),0);
            }
        }

        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self()); // 线程分离
            ThreadDate *td = static_cast<ThreadDate *>(args);
            logMessage(Info, "thread running...");

            td->_tsvp->ServerIO(td->_sock, td->_ip, td->_port);
            std::cout<<"["<<td->_ip<<"]-["<<td->_port<<"] quit..."<<std::endl;
            delete td;
            return nullptr;
        }

        // 服务器开始运行
        void Start()
        {
            while (true)
            {
                std::string clientIp;
                uint16_t clientPort;
                _sock = _listenSock.Accept(clientIp, clientPort);
                if (_sock < 0)
                    continue;
                logMessage(Info, "accept a new client,Ip:%s,port:%d", clientIp.c_str(), clientPort);
                // 多线程运行
                pthread_t tid;
                ThreadDate *td = new ThreadDate(_sock, clientIp, clientPort, this);
                pthread_create(&tid, nullptr, ThreadRoutine, td);
            }
        }

    private:
        int _sock;
        uint16_t _port;
        Sock _listenSock;
        func_t _func;
    };
}